﻿using Framework.Core.Consts;
using Framework.Core.Options;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Framework.AspNetCore.Extensons
{
	public static class JWTAuthorizationServiceCollectionExtensions
	{
		/// <summary>
		/// 添加 JWT 授权
		/// </summary>
		/// <param name="services"></param>
		/// <returns></returns>
		public static IServiceCollection AddJwt(this IServiceCollection services)
		{
			var configuration = services.GetConfiguration();
			var jwtOptions = configuration.GetSection(nameof(JwtOptions)).Get<JwtOptions>();
			var refreshJwtOptions = configuration.GetSection(nameof(RefreshJwtOptions)).Get<RefreshJwtOptions>();

			services.AddAuthentication(options =>
			{
				options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
				options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
			})
			.AddJwtBearer(_ =>
			{
				_.TokenValidationParameters = new TokenValidationParameters
				{
					ClockSkew = TimeSpan.Zero,
					ValidateIssuerSigningKey = true,
					ValidIssuer = jwtOptions.Issuer,
					ValidAudience = jwtOptions.Audience,
					IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey))
				};
				_.Events = new JwtBearerEvents
				{
					OnMessageReceived = context =>
					{
						var accessToken = context.Request.Query["access_token"];
						if (!string.IsNullOrEmpty(accessToken))
						{
							context.Token = accessToken;
						}
						return Task.CompletedTask;
					}
				};
			})
			.AddJwtBearer(TokenTypeConst.Refresh, _ =>
			{
				_.TokenValidationParameters = new TokenValidationParameters
				{
					ClockSkew = TimeSpan.Zero,
					ValidateIssuerSigningKey = true,
					ValidIssuer = refreshJwtOptions.Issuer,
					ValidAudience = refreshJwtOptions.Audience,
					IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
				};
				_.Events = new JwtBearerEvents
				{
					OnMessageReceived = context =>
					{
						var refresh_token = context.Request.Headers["refresh_token"];
						if (!string.IsNullOrEmpty(refresh_token))
						{
							context.Token = refresh_token;
							return Task.CompletedTask;
						}
						var refreshToken = context.Request.Query["refresh_token"];
						if (!string.IsNullOrEmpty(refreshToken))
						{
							context.Token = refreshToken;
						}

						return Task.CompletedTask;
					}
				};

			});
			return services;
		}
	}
}
